#ifndef SELF_DEFINE_FUNCTIONS_H_INCLUDED
#define SELF_DEFINE_FUNCTIONS_H_INCLUDED


#include "./CEC2013/cec2013.h"
#include <math.h>
#include <boost/random.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/cauchy_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/uniform_real.hpp>
#include <vector>


using namespace std;

const int timesOfRun = 51;


const double epsilon_set[] = {1e-1,1e-2,1e-3,1e-4,1e-5};
const int epsilon_set_size = 5;


struct NewType
{
    double data;
    int id;
};


bool Compare_NewType( NewType data1, NewType data2 );

double Fitness ( double *particle, int &Fes, CEC2013 *pFunc );

void Popupation_Fitness( double **population, int population_size, int &Fes, double *result, CEC2013 *pFunc );

double Distance( double *vector1, double *vector2, int dim );

double Distance( double *vector1, vector<double> vector2, int dim );

void Get_Seeds( double **population, double *population_results, int population_size, int dim, vector<double> &seed_fitness, double radius );

int How_Many_Global_Optima( vector<double> seed_fitness, double epsilon, CEC2013 *pFunc );

int Compute_Global_Optima_Found( double **population, double *population_results, int population_size, int dim, double epsilon, CEC2013 *pFunc );

int Close_Particle( double *child, double **population, int population_size, int dim );

int Close_Particle( double *dist,  int population_size );

void Dist_Individual_to_All( double *dist, double *individual, double **population, int population_size, int dim );

void Dist_All_to_All( double **population, double **dist, int population_size, int dim );

void Update_Dist( double **dist, double *temp_dist, int closet_individual, int population_size );

void Sort_Population_Dist( double *dist, int *sorted_index, int population_size );

void Sort_Population_Fitness( double *population_results, int *sorted_index, int population_size, double &population_fitness_gap );

void Ranking( double *population_results, int *ranking, int population_size, double &fitness_gap );

void Get_Nearest_M_Individuals( double *dist, bool *flag, int *Nearest_M, int population_size, int n_nearest );

void Get_Species( int **species, int seed_num, int species_size, int last_species_size,  double **dist, int *sorted_index, int *seed_location, int population_size );

void Get_Seed_Location( int *seed_location, double *population_results, int **species, int species_num, int speices_size, int last_species_size );

void Seed_Local_Prob( double *seed_local_prob, int *seed_location, double *population_results, int species_num );

void Local_Species_Evolve(  double **population, double *population_results, double *LBound, double *UBound, int seed_location,
                            int dim,  double local_std_value , int &Fes, CEC2013 *pFun, int sample_num );

void Local_Species_Evolve(  double **population, double *population_results, double *LBound, double *UBound, int seed_location,
                            int dim,  double local_std_value , int &Fes, CEC2013 *pFun, int sample_num, int &local_search_fail );

void Local_Evolve(  double **population, double *population_results, double *LBound, double *UBound, double *seed_local_prob, int *seed_location,
                    int dim, int species_num,  double local_std_value, int &Fes, CEC2013 *pFun, int sample_num );


void Weight_in_Species( double *weight, int *species, double*population_results, int species_size, double population_fitness_gap );

void Probability_in_Species( double *probability,  double *weight, int species_size );

double Cal_Variance( int *species, double **population, int dim_index, double dim_value,  int species_size );

void Cal_Variance( double *variance, int *species, double **population, double *selected_individual,  int species_size, int dim );

int Selected_Individual( double *probability, int species_size );


void Species_Evolve_At_Individual3( int *species, double **population, double*population_results, double **child, double *LBound, double *UBound,int seed_location,
                                    int dim, int species_size, double population_fitness_gap );


void Evolve_At_Individual3( int **species, double **population, double *population_results, double **child, double *LBound, double *UBound,int *seed_location,
                            int dim, int species_num, int n_nearest, int last_species_size, double population_fitness_gap );


void Selection( int **species, double **population, double **child, double *population_results, double *child_results, int* seed_location,
                int species_size, int species_num, int last_species_size, int population_size, int dim );

void Update_Dist_Seed( double **dist, int *seed_location, double **population, int population_size, int seed_num, int dim );



#endif // SELF_DEFINE_FUNCTIONS_H_INCLUDED
